
#region Using Statements

using System;

using Castle.Core;
using Castle.MicroKernel;

using FamilyTreeProject.Data.Repositories;

#endregion;

namespace FamilyTreeProject.ComponentModel
{
    /// <summary>
    /// The Container Class provides Inversion of Control for the
    /// Project.  It is used to register and fetch the 
    /// pluggable components used by the project.
    /// </summary>
    public class Container
    {

        private static IKernel kernel = new DefaultKernel();

        /// <summary>
        /// GetService fetches a service
        /// </summary>
        /// <remarks>This overload returns the "first" or default implementation
        /// of the TService type</remarks>
        /// <typeparam name="TService">The type of Service to return</typeparam>
        /// <returns>The default instance of the type of Repository</returns>
        public static TService GetService<TService>()
        {
            return (TService)kernel[typeof(TService)];
        }

        /// <summary>
        /// GetService fetches a service
        /// </summary>
        /// <remarks>This overload returns a specific concrete Implementation
        /// (TClass) of the TService type.</remarks>
        /// <typeparam name="TService">The type of Service</typeparam>
        /// <typeparam name="TClass">The type of the specific concrete implementation of the Service to return</typeparam>
        /// <returns>An instance of the specified type of Service</returns>
        public static TClass GetService<TService, TClass>()
        {
            Type classType = typeof(TClass);
            String key = classType.FullName;

            return (TClass)kernel[key];
        }

        /// <summary>
        /// GetService fetches a service
        /// </summary>
        /// <remarks>This overload returns a specific Instance of specifc concrete Implementation
        /// (TClass) of the TService type.</remarks>
        /// <typeparam name="TService">The type of Service</typeparam>
        /// <typeparam name="TClass">The type of the specific concrete implementation of the Service to return</typeparam>
        /// <param name="name">The name of the instance.</param>
        /// <returns>An instance of the specified type of Service</returns>
        public static TClass GetService<TService, TClass>(string name)
        {
            Type classType = typeof(TClass);
            String key = classType.FullName;
            if (! String.IsNullOrEmpty(name))
                key += "_" + name;

            return (TClass)kernel[key];
        }

        /// <summary>
        /// RegisterService registers a service
        /// </summary>
        /// <typeparam name="TService">The type of Service</typeparam>
        /// <typeparam name="TClass">The type of a specific Service Implementation</typeparam>
        public static void RegisterService<TService, TClass>()
        {
            Type serviceType = typeof(TService);
            Type classType = typeof(TClass);
            String key = classType.FullName;

            kernel.AddComponent(key, serviceType, classType, LifestyleType.Singleton);
        }

        /// <summary>
        /// RegisterService registers a service
        /// </summary>
        /// <typeparam name="TService">The type of Service</typeparam>
        /// <typeparam name="TClass">The type of a specific Service Implementation</typeparam>
        /// <param name="name">The name of the instance.</param>
        /// <param name="instance">The instance to register.</param>
        public static void RegisterService<TService, TClass>(string name, TClass instance)
        {
            Type classType = typeof(TClass);
            String key = classType.FullName;
            if (!String.IsNullOrEmpty(name))
                key += "_" + name;

            kernel.AddComponentInstance(key, typeof(TService), instance);
        }

    }
}
